/**
 * @(#)IBatisDao.java 2009-12-11
 * 
 * Copyright (c) 2000-2009 by ChinanetCenter Corporation.
 *
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * ChinanetCenter Corporation ("Confidential Information").  You
 * shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement
 * you entered into with ChinanetCenter.
 * 
 */

package com.szf.base.dao.ibatis;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import org.springframework.stereotype.Repository;

import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapException;
import com.ibatis.sqlmap.engine.impl.SqlMapClientImpl;
import com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate;
import com.szf.util.CountStatementUtils;

@Repository
@SuppressWarnings("unchecked")
public final class IBatisDao extends SqlMapClientDaoSupport {

	private final Logger logger = LoggerFactory.getLogger(IBatisDao.class);

	// namespace
	//	private String ns;

	@Autowired(required = true)
	public void setSqlMapClientWorkAround(SqlMapClient sqlMapClient) {
		this.setSqlMapClient(sqlMapClient);
	}

	/**
	 * 用于Dao层子类使用的构造函数. 通过子类的NameSpace定义取得namespace.
	 */
	public IBatisDao() {
		//		if (getClass().isAnnotationPresent(NameSpace.class)) {
		//			NameSpace p = getClass().getAnnotation(NameSpace.class);
		//			ns = p.value();
		//		}
	}

	/**
	 * 用于省略Dao层, Service层直接使用通用IBatisDao的构造函数.
	 * 在构造函数中定义namespace.
	 */
	public IBatisDao(String namespace) {
		//		ns = namespace;
	}

	//-- 通用数据库操作 --//

	private String getRealId(String id) {
		// 暂定使用该功能
		//		if (ns != null) {
		//			return ns + "." + id;
		//		}
		//		else {
		return id;
		//		}
	}

	public <X> X queryForObject(String id) {
		return (X) this.getSqlMapClientTemplate().queryForObject(getRealId(id));
	}

	public <X> X queryForObject(String id, Object param) {
		return (X) this.getSqlMapClientTemplate().queryForObject(getRealId(id), param);
	}

	public <X> X queryForObject(String id, Object param, Object result) {
		return (X) this.getSqlMapClientTemplate().queryForObject(getRealId(id), param, result);
	}

	public <X> List<X> queryForList(String id) {
		return this.getSqlMapClientTemplate().queryForList(getRealId(id));
	}

	public <X> List<X> queryForList(String id, Object param) {
		return this.getSqlMapClientTemplate().queryForList(getRealId(id), param);
	}

	public <X> X insert(String id, Object object) {
		return (X) this.getSqlMapClientTemplate().insert(id, object);
	}

	public int update(String id, Object object) {
		return this.getSqlMapClientTemplate().update(id, object);
	}

	public int delete(String id, Object object) {
		return this.getSqlMapClientTemplate().delete(id, object);
	}

	// TODO add more...

	/**
	 * IBATIS的分页查询
	 * @param statementId
	 * @param value
	 * @param offset
	 * @param size
	 * @return 查询的记录集,记录数
	 */
	private IBatisResult queryPageForListBySql(String statementId, Object value, int offset,
			int size) {
		//List<?> total = this.getSqlMapClientTemplate().queryForList(statementId, value);
		Long total = this.queryForTotal(statementId, value);
		//		if (value instanceof Map) {
		//			HashMap hs = (HashMap) value;
		//			hs.put("offset", offset);
		//			hs.put("size", size);
		//		}
		List<?> list = this.getSqlMapClientTemplate()
				.queryForList(statementId, value, offset, size);
		return new IBatisResult(total.intValue(), list);
	}

	/**
	 * 获取总数
	 */
	private Long queryForTotal(String statementId, Object value) {
		// prepare CountStatement
		String countStatementId = CountStatementUtils.getCountStatementId(statementId);
		SqlMapExecutorDelegate delegate = ((SqlMapClientImpl) getSqlMapClientTemplate()
				.getSqlMapClient()).getDelegate();
		// 判断是否已经转换过
		try {
			delegate.getMappedStatement(countStatementId);
		}
		catch (SqlMapException e) {
			logger.debug("add count statement: {}", countStatementId);
			delegate.addMappedStatement(CountStatementUtils.createCountStatement(delegate
					.getMappedStatement(statementId)));
		}
		// do query
		return (Long) this.getSqlMapClientTemplate().queryForObject(countStatementId, value);
	}

	/**
	 * 根据IBatisPage(IBatis查询条件及分页管理包装类)查询符合条件的对象，把查询结果list及count放置到该QueryInfo并返回
	 *
	 * @param queryInfo IBatis查询条件及分页管理包装类
	 * @return queryInfo 包含查询结果list及count的SQueryInfo
	 */
	public IBatisPage query(IBatisPage queryInfo) {
		String statementId = queryInfo.getStatementId();
		Object paramValue = queryInfo.getParamValue();
		int offset = queryInfo.getOffset();
		int size = queryInfo.getPageSize();

		//取得查询结果列表
		IBatisResult result = this.queryPageForListBySql(statementId, paramValue, offset, size);
		queryInfo.setQueryList(result.getRecord());
		queryInfo.setRecordCount(result.getTotal());
		//返回QueryInfo
		return queryInfo;
	}

	private static class IBatisResult {
		private final int total;
		private final List<?> record;

		public IBatisResult(int total, List<?> record) {
			this.total = total;
			this.record = record;
		}

		public int getTotal() {
			return total;
		}

		public List<?> getRecord() {
			return record;
		}
	}

}
